// ts 的兼容性是基于安全来考虑  谁能赋予给谁

// 基本类型  -> 联合类型  (对于基本类型而言 )
let a1!: string | number;
let a2!: string | number | boolean;

// 如果我把a2 给了a1    a2 可能是一个bookean ， 那么boolean类型可以赋予给string | number
// a1 = a2;

// 出于安全考虑 我们定义的接口类型  ，只要满足这个接口就可以. 没有标识的方法不能被调用
interface IHasToString {
  toString(): string;
}
let str: IHasToString = "hello"; // hello里面具备了各种各样的方法 其中包含了toString

// 接口的兼容性 两个接口 多的是不能赋予给少的

interface IFruit1 {
  color: String;
  taste: String;
  size: number;
}
interface IFruit2 {
  color: String;
  taste: String;
}
let f1!: IFruit1;
let f2!: IFruit2;
// 我约定好 后端返回的数据有5个字段 但是我调用完毕后多了5个

f2 = f1; // 当我们把一个变量赋予给另一个变量的时候 会发生类型兼容性
// f2 = f1

// 函数的兼容性   主要考虑函数的参数和返回值
// 参数在定义的时候 可以声明多个 ，使用的时候 可以小于等于我们的参数个数
// 对于返回值而言 我们可以从安全性考虑
let a = (a: string, b: string): string => "abc";
let b = (a: string): string => "abc";

// a=b
// [].map((item)=>{} )

// 逆变和协变  （参数是逆变的 返回值是协变的） 在使用函数传参的时候 可以传递父亲 返回儿子  （传父返子）
class GrandParent {
  house: string = "房子";
}
class Parent extends GrandParent {
  money: string = "钱";
}
class Son extends Parent {
  play: string = "玩";
}
 
// 类型中的Parent是实例  （传父返子） 函数的参数是逆变的可以传递父亲 函数的返回值是协变的只能传递儿子
function getFn(cb: (val: Parent) => Parent) {

}
// 我传递的参数要保证你能处理 ， 返回的结果要求符合你所有的属性


// 可以配置参数 允许双向协变 可以乱传
getFn((val: Parent) => new Parent());



// 传父返子
function getFn1(cb:(val: number | boolean) => string | boolean) {

}

getFn1((val:boolean | number | string):boolean => false)

// 枚举的结果结果永远无法兼容
enum A {
  
}
enum B{

}
let c2:A;
let d2:B;

//  类的兼容 只要你有的我有就可以
class Animal {
  private name:string
}
class Person {
  private name:string
}
let animal:Animal = new Animal
let person :Person = new Person
// animal = person; // 比较的是实例 , 如果两个人带有修饰器 除public之外的永远都不相等
export {};




